<?php

declare(strict_types=1);

namespace app\common\service\user;

use app\common\service\BaseService;
use app\common\repository\user\UserBalanceLogRepository;
use think\facade\Db;
use think\helper\Str;

class UserBalanceLogService extends BaseService
{
    const Content_Casting_Revenue = 'content_casting_revenue'; // 内容铸造
    const Liquidity_Income = 'liquidity_income'; // 流动性挖矿
    const REWARD_TYPE_TEAM = 'team_incentive_codex'; // 团队激励
    const REWARD_TYPE_PEER = 'peer_reward';           // 平级奖励
    const REWARD_TYPE_SURPASS = 'surpass_reward';     // 超越奖励
    const REWARD_TYPE_RECOMMEND = 'recommended_income'; // 推荐奖励

    const Recommended_Income = 'recommended_income'; // 直推奖励
    const TeamIncentiveCodex = 'team_incentive_codex'; // 团队奖励
    const MINING_PROFIT     = 'mining_profit_release';
    const INVITE_REWARD     = 'invite_reward';
    const WITHDRAW_APPLY    = 'withdraw_apply'; // 提现
    const WITHDRAW_FAIL     = 'withdraw_fail';
    const DEPOSIT_SUCCESS   = 'deposit_success';
    const TRANSFER_IN       = 'transfer_in';
    const TRANSFER_OUT      = 'transfer_out';

    public static function getDesc(string $type): string
    {
        $map = [
            self::MINING_PROFIT   => '挖矿收益',
            self::INVITE_REWARD   => '邀请奖励',
            self::WITHDRAW_APPLY  => '提现申请',
            self::WITHDRAW_FAIL   => '提现失败',
            self::DEPOSIT_SUCCESS => '充值成功',
            self::TRANSFER_IN     => '转账到账',
            self::TRANSFER_OUT    => '转账支出',
        ];
        return $map[$type] ?? $type;
    }

    public function __construct(UserBalanceLogRepository $repository)
    {
        $this->repository = $repository;
    }

    // ========================
    // CRUD 方法（已存在，保留）
    // ========================

    /**
     * 获取列表（全部，无条件）
     *
     * @return \think\model\Collection|\think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getList(): \think\model\Collection|\think\Collection
    {
        return $this->repository->getByWhere([], ['create_time' => 'desc']);
    }

    /**
     * 新增日志
     *
     * @param array $data
     * @return \think\Collection|\app\common\model\BaseModel|array
     * @throws \Exception
     */
    public function create(array $data): \think\Collection|\app\common\model\BaseModel|array
    {
        return $this->repository->save($data);
    }

    /**
     * 修改日志
     *
     * @param array $data
     * @param mixed $where
     * @return \app\common\model\BaseModel|bool|int
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function update(array $data, $where): \app\common\model\BaseModel|bool|int
    {
        return $this->repository->update($data, $where);
    }

    /**
     * 获取详情
     *
     * @param mixed $where
     * @return \app\common\model\BaseModel|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getInfo($where): ?\app\common\model\BaseModel
    {
        return $this->repository->getOne($where);
    }

    /**
     * 删除日志
     *
     * @param mixed $where
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function delete($where): bool
    {
        return $this->repository->delete($where);
    }

    // ========================
    // 业务专用方法（新增）
    // ========================

    /**
     * 添加资产变动日志（核心方法）
     *
     * @param $userId
     * @param string $bizType 业务类型
     * @param string $coinType 币种：codex | usdt
     * @param float|string $amount 变动金额
     * @param string|null $relatedId 关联ID
     * @param string|null $remark 备注
     * @param string $changeType increase|decrease（可自动判断）
     * @return bool
     */
    public function addLog(
        $userId,
        string       $bizType,
        string       $coinType,
        float|string $amount,
        ?string      $relatedId = null,
        ?string      $remark = null,
        string       $changeType = ''
    ): bool {
        $amount = (float)$amount;
        if ($amount <= 0) {
            return false;
        }

        // 自动判断变动类型
        if (empty($changeType)) {
            $changeType = $amount > 0 ? 'increase' : 'decrease';
            $amount = abs($amount);
        }

        // 获取当前余额（从 user_account 表）
        $currentBalance = $this->getCurrentBalance($userId, $coinType);
        $balanceAfter = $changeType === 'increase'
            ? $currentBalance + $amount
            : $currentBalance - $amount;

        $balanceAfter = round($balanceAfter, 8);

        if ($balanceAfter < 0) {
            trace("UserBalanceLogService::addLog failed: balance would be negative for user {$userId}", 'error');
            return false;
        }

        $data = [
            'user_id'        => $userId,
            'biz_type'       => $bizType,
            'change_type'    => $changeType,
            'coin_type'      => $coinType,
            'amount'         => round($amount, 8),
            'balance_after'  => $balanceAfter,
            'related_id'     => $relatedId,
            'remark'         => $remark,
            'create_time'    => time(),
        ];

        try {
            // ✅ 使用 Repository 保存（而不是直接 Db::name）
            $this->repository->save($data);
            return true;
        } catch (\Exception $e) {
            trace('UserBalanceLogService::addLog error: ' . $e->getMessage(), 'error');
            return false;
        }
    }

    /**
     * 获取用户当前余额（用于 balance_after 计算）
     *
     * @param $userId
     * @param $coinType
     * @return float
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    protected function getCurrentBalance($userId, $coinType): float
    {
        $field = $coinType . '_balance';
        $account = Db::name('user_account')
            ->where('user_id', $userId)
            ->field($field)
            ->find();

        return (float)($account ? $account[$field] : 0.0);
    }

    /**
     * @param $userId
     * @param string|null $bizType
     * @param string|null $coinType
     * @param int $page
     * @param int $limit
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getLogList(
        $userId,
        ?string $bizType = null,
        ?string $coinType = null,
        int $page = 1,
        int $limit = 20
    ): array {
        $query = [];
        if ($bizType) {
            $query['biz_type'] = $bizType;
        }
        if ($coinType) {
            $query['coin_type'] = $coinType;
        }
        $query['user_id'] = $userId;

        $list = $this->repository->getByWhere(
            $query,
            ['create_time' => 'DESC'],
            $page,
            $limit
        );

        $total = $this->repository->count($query);

        return [
            'list'  => $list,
            'total' => $total,
            'page'  => $page,
            'limit' => $limit,
        ];
    }

    /**
     * 统计用户某类收益总额
     *
     * @param $userId
     * @param string $bizType
     * @param string $coinType
     * @return float
     */
    public function sumProfit($userId, string $bizType, string $coinType): float
    {
        $sum = $this->repository->sum([
            'user_id'     => $userId,
            'biz_type'    => $bizType,
            'coin_type'   => $coinType,
            'change_type' => 'increase'
        ], 'amount');

        return (float)$sum;
    }

    /**
     * 获取资产记录
     *
     * @param $user_id
     * @param string $biz_type
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     */
    public function getUserBalanceLog($user_id, string $biz_type = ''): array
    {
        [$page, $pageSize] = $this->getPaginationParams();
        $where['user_id'] = $user_id;
        if(!empty($biz_type)) {
            $where['biz_type'] = $biz_type;
        }
        return $this->repository->paginate($where, ['create_time' => 'desc'], $page, $pageSize);
    }
}